/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ruipengkj.component.jtree;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultTreeModel;

import com.ruipengkj.commons.BuildSpringApplication;
import com.ruipengkj.service.TProductCatalogService;

/**
 *
 * @author vearn
 */
public class TestFrame extends JFrame {
	static{
		BuildSpringApplication.getInstance();
	}
	private TProductCatalogService tProductCatalogService;
    public TestFrame() throws Exception{
        super("asynch_load_tree");
        tProductCatalogService=BuildSpringApplication.getInstance().getTProductCatalogServiceImpl();
        
        JPanel northPanel = new JPanel();
        final JCheckBox cb = new JCheckBox("点我看长时间阻塞EDT的后果");
        northPanel.add(cb);
        JPanel southPanel = new JPanel();
        final JLabel label = new JLabel("异步加载树DEMO");
        southPanel.add(label);
        
        
        final DefaultTreeModel treeModel = initTreeModel();
        final JTree tree = new JTree(treeModel); //  JTree构造方法
        tree.setShowsRootHandles(true); //  显示根结点左边的控制手柄
        tree.collapseRow(0);    //  初始时只显示根结点
        //  注册TreeExpansionListener、监听结点展开事件
        tree.addTreeExpansionListener(new TreeExpansionListener() {
            @Override
            public void treeExpanded(TreeExpansionEvent event) {
                //  首先获取展开的结点
                final OverwriteDefaultMutableTreeNode expandNode = (OverwriteDefaultMutableTreeNode) event.getPath().getLastPathComponent();
                //  判断该节点是否已经被访问过
                //  是——无需到数据库中读取、什么事也不做
                //  否——开始异步加载
                if (!expandNode.isVisited()) {
                    expandNode.setVisited(true);    //  先改变visited字段的状态
                    tree.setEnabled(false); //  暂时禁用JTree

                    //  更新JLabel信息
                    label.setText("正在加载结点[" + expandNode.getNodeName() + "]...");
                    if (cb.isSelected()) {
                        long handleTime = asynchLoad(expandNode, treeModel);
                        treeModel.removeNodeFromParent(expandNode.getFirstLeaf());  //  加载完毕后要删除“载入中...”结点
                        tree.setEnabled(true);  //  使JTree可用
                        label.setText("加载结点[" + expandNode.getNodeName() + "]完毕、耗时" + handleTime + "ms");
                    } else {
                        //  使用swingworker框架
                        new SwingWorker<Long, Void>() {
                            @Override
                            protected Long doInBackground() throws Exception {
                                return asynchLoad(expandNode, treeModel);
                            }

                            @Override
                            protected void done() {
                                treeModel.removeNodeFromParent(expandNode.getFirstLeaf());
                                treeModel.nodeStructureChanged(expandNode); //  通知视图结构改变
                                tree.setEnabled(true);
                                try {
                                    //  获取doInBackground方法的返回值
                                    label.setText("加载结点[" + expandNode.getNodeName() + "]完毕、耗时" + get() + "ms");
                                } catch (Exception ex) {
                                }
                            }
                        }.execute();
                    }
                }
            }

            @Override
            public void treeCollapsed(TreeExpansionEvent event) {
            }
        });

        getContentPane().add(northPanel, BorderLayout.NORTH);
        getContentPane().add(southPanel, BorderLayout.SOUTH);
        getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600, 450);
    }

    public static void main(String args[]) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());    //  设定界面观感
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
					new TestFrame().setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
            }
        });
    }

    //  从数据库中读取根结点、并增加“载入中...”子结点
    private DefaultTreeModel initTreeModel() throws Exception{
        DefaultTreeModel treeModel = null;
//        List<TProductCatalog> list=tProductCatalogService.findChildByParentCatalogIDService(0);
//        OverwriteDefaultMutableTreeNode root = new OverwriteDefaultMutableTreeNode(0, "所有产品");
//        treeModel = new DefaultTreeModel(root);
//        try {
//          for(int i=0;i<list.size();i++){
//        	  TProductCatalog key=list.get(i);
//        	  OverwriteDefaultMutableTreeNode child = new OverwriteDefaultMutableTreeNode(key.getId(), key.getName());
//        	  root.add(child);
//              if (key.getTProductCatalog()!=null) {
//                  addLoadingNode(treeModel, root);
//              }
//           }
//        } catch (Exception ex) {
//        	ex.printStackTrace();
//        } 
        return treeModel;
    }

    //  增加“载入中...”子结点的方法
    private void addLoadingNode(DefaultTreeModel treeModel, OverwriteDefaultMutableTreeNode parent) {
    	OverwriteDefaultMutableTreeNode loading = new OverwriteDefaultMutableTreeNode("载入中...");
        treeModel.insertNodeInto(loading, parent, parent.getChildCount());
    }

    //  从数据表中读取expandNode的子结点.返回值为处理时长
    private long asynchLoad(OverwriteDefaultMutableTreeNode expandNode, DefaultTreeModel treeModel) {
        long handleTime = 0L;   //  本次异步加载的处理时长
        long start = System.currentTimeMillis();    //  开始处理的时刻

        //  从数据库中读取父结点是expandNode的所有记录
        try {
//            Thread.sleep(3000); //  sleep一段时间以便看清楚整个过程
//            List<TProductCatalog> list=tProductCatalogService.findChildByParentCatalogIDService(expandNode.getNodeId());
//            for(int i=0;i<list.size();i++){
//            	TProductCatalog key=list.get(i);
//            	OverwriteDefaultMutableTreeNode obj = new OverwriteDefaultMutableTreeNode(key.getId(),key.getName());
//                //  如果此结点不是叶子节点
//                //  给它加上一个“载入中...”的子结点
//                //  使这个结点左边绘制控制手柄.点击它(或者双击这个结点)可以触发TreeExpansionEvent
//            	 if (key.getTProductCatalogs()!=null) {
//                     addLoadingNode(treeModel, obj);
//                 }
//                //  把这个节点加入到expandNode中
//                treeModel.insertNodeInto(obj, expandNode, expandNode.getChildCount());
//            }
        } catch (Exception ex) {
        	ex.printStackTrace();
        } finally {
            handleTime = System.currentTimeMillis() - start;    //  计算出处理时长
        }
        return handleTime;
    }
}